
from querier.esquerier import ElasticSearchQuerier
import utils.utils as uc
from querier.weibo import utils


READ = 'read_num'
LIKE = 'like_num'
RATIO = 'like_read_ratio'
RELATIVE = 'relative'

DAYS = 15
MINIMUM_SHOULD_MATCH = '5<85% 10<9'
MAX_CHARACTER = 30
CATEGORY_CUTOFF = 0.9
MAX_KEYWORDS = 10


class WeiboTopicSearchQuerier(ElasticSearchQuerier):
    def __init__(self, es, index, doc_type, nlp_service=None):
        super(WeiboTopicSearchQuerier, self).__init__(es, index, doc_type)
        self.nlp_service = nlp_service

    def _build_query(self, args):
        term = args.get('term', '')
        term = term if term else ''
        filters = args.get('filters', {})
        if filters is None:
            filters = {}
        order = args.get('order_by', uc.ORDER_OVERALL)
        from_ = args.get('from', 0)
        size_ = args.get('size', 10)

        query = self._gen_query(term, filters, from_, size_)

        return query, {}, {'order': order}

    def _build_result(self, es_result, param):
        # order = param['order']
        total = es_result['hits']['total']
        topics = []
        for hit in es_result['hits']['hits']:
            topics.append(self.extract_result(hit))
        return {
            'total': total,
            'topics': topics
        }

    @staticmethod
    def _gen_query(term, filters, from_, size_):
        should_clause = []
        filter_clause = []
        if filters:
            filter_clause = utils.add_filter_range_clause(filter_clause, filters, 'topic_length')
            filter_clause = utils.add_filter_clause(filter_clause, filters, 'topic_type', 'should')
            filter_clause = utils.add_filter_range_clause(filter_clause, filters, 'date')

        if term:
            term = term.strip()
            if len(term) <= 5:
                should_clause.append(
                    {
                        'match_phrase': {
                            "topic": {
                                'query': term[0:MAX_CHARACTER],
                                'slop': 1,
                                'boost': 3,
                            },

                        }
                    }
                )
            else:
                should_clause.append(
                    {
                        'match': {
                            "topic": {
                                'query': term[0:MAX_CHARACTER],
                                'boost': 3,
                                'minimum_should_match': MINIMUM_SHOULD_MATCH
                            },

                        }
                    }
                )

        query = {"query": {
            "bool": {
                # "must": must_clause,
                # "should": should_clause,
                "filter": filter_clause,
                # "must": {'bool': {}},
                # "minimum_should_match": 1
            }
        }, 'from': from_, 'size': size_}

        if should_clause:
            query['query']['bool']['should'] = should_clause
            query['query']['bool']['minimum_should_match'] = 1

        query['sort'] = [
            {'sum_engagement': 'desc'},
            '_score'
        ]

        query['track_scores'] = True

        return query

    @staticmethod
    def extract_result(hit):
        source_ = hit['_source']

        return {
            'topic': source_.get('topic', ''),
            'sum_engagement': source_.get('sum_engagement'),
            'date': source_.get('date')

        }
